/***************************************************************************
 *   KShootout - online shootout card game.                                *
 *   Copyright (C) 2008, 2009  MacJariel                                   *
 *                                                                         *
 *   KShootout is free software: you can redistribute it and/or modify     *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation, either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   KShootout is distributed in the hope that it will be useful,          *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with KShootout.  If not, see <http://www.gnu.org/licenses/>.    *
 ***************************************************************************/
#ifndef __GAME_H__
#define __GAME_H__

#include "gametypes.h"
#include <QObject>
#include <QList>
#include <QMap>

class GameReplay;   /// @todo Create GameReplay class

namespace client
{
    class Player;
    class GameEventMgr;
    class GameActionMgr;
    class GameWidget;

    /**
     * The Game class represents a KShootout game. As soon as client joins a
     * game or starts a replay, a new Game instance is created and lives until
     * client leaves the game.
     * @author MacJariel <MacJariel@gmail.com>
     */
    class Game: public QObject
    {
        Q_OBJECT;
    public:
        /// Constructs a game object that will play game replay.
        explicit Game(const GameReplay&);

        /// Constructs a game object from enter-game event received from server.
        explicit Game(const EnterGameEventDataPtr&);

        /// Destroys the game.
        virtual ~Game();

        /// Returns the id of current player.
        PlayerId currentPlayerId() const;

        /// Returns current player.
        Player* currentPlayer() const;

         /// Returns the id of current player.
        PlayerId requestedPlayerId() const;

        /// Returns requested player.
        Player* requestedPlayer() const;

        /// Returns the id of local player or 0 if there is not local player.
        PlayerId localPlayerId() const;

        /// Returns local player or 0 if there is not local player.
        Player* localPlayer() const;

        /// Returns the current gameState.
        GameState gameState() const;

        /// Returns the current gamePlayState.
        GamePlayState gamePlayState() const;

        /// Adds new game event to the game. Game events are not processed directly
        /// by game instance, but instead they are delegated to GameEventMgr.
        /// @see GameEventMgr
        void addNewGameEvent(const GameEventDataPtr& newGameEvent);

        /// Processes the server event, or does nothing, if the server event
        /// is not suitable.
        void processServerEvent(const ServerEventDataPtr& serverEvent);

    private:
        const ActorId           m_actorId;
        const GameId            m_gameId;
        PlayerId                m_localPlayerId;
        ActorDataPtr            mp_actor;
        QList<ActorDataPtr>     m_actors;
        QString                 m_gameName;
        GameState               m_gameState;
        GameContextData* const  mp_gameContext;
        QMap<PlayerId, Player*> m_players;

        GameEventMgr* const     mp_gameEventMgr;
        GameActionMgr* const    mp_gameActionMgr;
        GameWidget* const       mp_gameWidget;
    };

    inline Player* Game::currentPlayer() const
    {
        return m_players.value(currentPlayerId());
    }

    inline Player* Game::requestedPlayer() const
    {
        return m_players.value(requestedPlayerId());
    }

    inline PlayerId Game::localPlayerId() const
    {
        return m_localPlayerId;
    }

    inline Player* Game::localPlayer() const
    {
        return m_players.value(localPlayerId());
    }

    inline GameState Game::gameState() const {
        return m_gameState;
    }
}
#endif // __GAME_H__

#if 0
/// THE FOLLOWING WILL MOVE TO GAMEWIDGET



/**
* Adds new opponent according to PlayerData. The opponent is
* added to first unused opponentWidget. This method should be used only
* before game is started, because the resulting player order may differ
* from the correct one.
*/
void appendPlayer(const PlayerData&);

/**
* Inserts new opponent according to PlayerData. The opponent is
* added to the OpponentWidget with given <i>index</i>. Index with positive
* value counts from the local player clock-wise, and with negative value
* counts counter-clock-wise.
*/
void insertPlayer(int index, const PlayerData&);

/**
* Removes the opponent with given <i>id</i>.
*/
void removePlayer(PlayerId id);

/**
* Updates the player according to PlayerData. First the right
* PlayerWidget is found and then this widget is updated with PlayerData.
*/
void updatePlayer(const PlayerData&);

/**
* Clears player widget specified with index. Negative indeces can be
* used.
*/
void clearPlayerWidget(int index);

/**
* Clears player widgets specified by index range. Negative indeces can be
* used.
*/
void clearPlayerWidgetRange(int indexFrom, int indexTo);




/**
* Returns the PlayerWidget of the player with given <i>id</i>
* or 0, if such PlayerWidget is not found.
*/
inline PlayerWidget* playerWidget(PlayerId id) const {
    return m_playerWidgets.value(id, 0);
    }

    /**
    * Returns the widget of local player, or 0 if game is in spectator mode.
    */
    inline LocalPlayerWidget* localPlayerWidget() const {
        return mp_localPlayerWidget;
        }

        /**
        * Returns the DeckWidget, or 0 if it was not created yet.
        */
        inline DeckWidget* deck() const {
            return mp_deck;
            }

            /**
            * Returns the GraveyardWidget. or 0 if it was not created yet.
            */
            inline GraveyardWidget* graveyard() const {
                return mp_graveyard;
            }

            /**
            * Returns the CardListWidget for selection pocket, or 0 if it was not
            * created yet.
            */
            inline CardListWidget* selection() const {
                return mp_selection;
            }




void syncGame(const GameSyncData& gameSyncData);



/**
* Sets the widget of the local player according to PlayerData.
* Does nothing in spectator mode.
*/
void setLocalPlayer(const PlayerData&);

/**
* Sets the state of the game.
*/
void setGameState(const GameState&);

/**
* Sets game context
*/
void setGameContext(const GameContextData&);

/**
* Sets the selection.
*/
void setSelection(QList<CardData>);

/**
* Sets the graveyard top card.
*/
void setGraveyard(const CardData&);



/**
* Changes the game interface, if necessary.
*/
void updateInterface();

/**
* Cleans the UI after leaving the game mode.
*/
void cleanUp();

/**
* Sets the text-info string.
*/
void setTextInfo(const QString&);

/**
* Unsets the text-info string.
*/
void unsetTextInfo();



#endif

